#include "stdafx.h"
#include "MGOptionImpl.h"

#if !defined(TUTILS_H_INCLUDED)
#include "TUtils.h"
#endif	// #if !defined(TUTILS_H_INCLUDED)

#ifndef REGISTRY_VALUE_H
#include "registry_value.h"
typedef registry_int<BOOL> regbool;
typedef registry_int<DWORD> regdword;
typedef registry_string<std::tstring> regtstring;
#endif	// #ifndef REGISTRY_VALUE_H

///////////////////////////////////////////////////////////////////////////////////////////////////////
// Shared variables among processes to apply options altogether
///////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma data_seg("SharedVariable")

BOOL sv_bAutoloadingOnStartup = TRUE;
BOOL sv_bPageTopBottom = TRUE;
BOOL sv_bPageUpDown = TRUE;
BOOL sv_bDblClkScrollingEnabled = TRUE;
BOOL sv_bMGSuspendingKeyEnabled = TRUE;
BOOL sv_bIdentifyTargetWindowClass = FALSE;
BOOL sv_bShowRecognitionOnStatusBar = TRUE;
BOOL sv_bPreemptiveMGAButtonAlways = FALSE;
BOOL sv_bMGEnabled = TRUE;
UINT sv_nPageTopBottomRecognitionArea = 5;
UINT sv_nDetectingRepeatedSameDirectionRate = 300;
UINT sv_nGestureRecognitionSensitivity = 15;
int sv_nMGSuspendingKey = VK_SHIFT;
enum MG::Button sv_MGAButton = MG::BUTTON_RIGHT;

BOOL sv_bUseMiddleButtonForDblClkScrolling = FALSE;

BOOL sv_bHelpTipEnabled = TRUE;
UINT sv_nDelayTimeHelpTip = 2000;

#pragma data_seg()

#pragma comment(linker, "/SECTION:SharedVariable,S")
///////////////////////////////////////////////////////////////////////////////////////////////////////
// End of Shared variables
///////////////////////////////////////////////////////////////////////////////////////////////////////

CMGOptionImpl::CMGOptionImpl()
{ 
}

void CMGOptionImpl::UpdateRegistry(BOOL bSaveAndValidate)
{
	// SECTION defined in stdafx.h
	// KEY## defined in MGConstant.h
	regbool rgbMGEnabled(SECTION KEY01, HKEY_CURRENT_USER);
	regdword rgdwMouseGestureActivationButton(SECTION KEY02, HKEY_CURRENT_USER);
	regbool rgbMGSuspendingKeyEnabled(SECTION KEY03, HKEY_CURRENT_USER);
	regdword rgdwMGSuspendingKey(SECTION KEY04, HKEY_CURRENT_USER);
	regbool rgbDblClkScrollingEnabled(SECTION KEY05, HKEY_CURRENT_USER);
	regbool rgbPageUpDown(SECTION KEY06, HKEY_CURRENT_USER);
	regbool rgbPageTopBottom(SECTION KEY07, HKEY_CURRENT_USER);
	regdword rgdwPageTopBottomRecognitionArea(SECTION KEY08, HKEY_CURRENT_USER);
	regdword rgdwGestureRecognitionSensitivity(SECTION KEY09, HKEY_CURRENT_USER);
	regdword rgdwDetectingRepeatedSameDirectionRate(SECTION KEY10, HKEY_CURRENT_USER);
	regbool rgbPreemptiveMGAButtonAlways(SECTION KEY12, HKEY_CURRENT_USER);
	regbool rgbShowRecognitionOnStatusBar(SECTION KEY13, HKEY_CURRENT_USER);
	regbool rgbIdentifyTargetWindowClass(SECTION KEY14, HKEY_CURRENT_USER);
	regbool rgbAutoloadingOnStartup(SECTION KEY15, HKEY_CURRENT_USER);

	regbool rgbUseMiddleButtonForDblClkScrolling(SECTION KEY16, HKEY_CURRENT_USER);
	regbool rgbEnableHelpTip(SECTION KEY17, HKEY_CURRENT_USER);
	regdword rgdwDelayTimeHelpTip(SECTION KEY18, HKEY_CURRENT_USER);
	
	if (bSaveAndValidate)
	{
		// write to the registry
		rgbMGEnabled = sv_bMGEnabled;
		rgdwMouseGestureActivationButton = (DWORD)sv_MGAButton;
		rgbMGSuspendingKeyEnabled = sv_bMGSuspendingKeyEnabled;
		rgdwMGSuspendingKey = (DWORD)sv_nMGSuspendingKey;
		rgbDblClkScrollingEnabled = sv_bDblClkScrollingEnabled;
		rgbPageUpDown = sv_bPageUpDown;
		rgbPageTopBottom = sv_bPageTopBottom;
		rgdwPageTopBottomRecognitionArea = sv_nPageTopBottomRecognitionArea;
		rgdwGestureRecognitionSensitivity = sv_nGestureRecognitionSensitivity;
		rgdwDetectingRepeatedSameDirectionRate = sv_nDetectingRepeatedSameDirectionRate;
		rgbPreemptiveMGAButtonAlways = sv_bPreemptiveMGAButtonAlways;
		rgbShowRecognitionOnStatusBar = sv_bShowRecognitionOnStatusBar;
		rgbIdentifyTargetWindowClass = sv_bIdentifyTargetWindowClass;
		rgbAutoloadingOnStartup = sv_bAutoloadingOnStartup;

		rgbUseMiddleButtonForDblClkScrolling = sv_bUseMiddleButtonForDblClkScrolling;
		rgbEnableHelpTip = sv_bHelpTipEnabled;
		rgdwDelayTimeHelpTip = sv_nDelayTimeHelpTip;
	}
	else
	{
		// read from the registry
		sv_bMGEnabled = rgbMGEnabled;
		sv_MGAButton = enum MG::Button((DWORD)rgdwMouseGestureActivationButton);
		sv_bMGSuspendingKeyEnabled = rgbMGSuspendingKeyEnabled;
		sv_nMGSuspendingKey = (DWORD)rgdwMGSuspendingKey;
		sv_bDblClkScrollingEnabled = rgbDblClkScrollingEnabled;
		sv_bPageUpDown = rgbPageUpDown;
		sv_bPageTopBottom = rgbPageTopBottom;
		sv_nPageTopBottomRecognitionArea = rgdwPageTopBottomRecognitionArea;
		sv_nGestureRecognitionSensitivity = rgdwGestureRecognitionSensitivity;
		sv_nDetectingRepeatedSameDirectionRate = rgdwDetectingRepeatedSameDirectionRate;
		sv_bPreemptiveMGAButtonAlways = rgbPreemptiveMGAButtonAlways;
		sv_bShowRecognitionOnStatusBar = rgbShowRecognitionOnStatusBar;
		sv_bIdentifyTargetWindowClass = rgbIdentifyTargetWindowClass;
		sv_bAutoloadingOnStartup = rgbAutoloadingOnStartup;

		sv_bUseMiddleButtonForDblClkScrolling = rgbUseMiddleButtonForDblClkScrolling;
		sv_bHelpTipEnabled = rgbEnableHelpTip;
		sv_nDelayTimeHelpTip = rgdwDelayTimeHelpTip;
	}
}

BOOL CMGOptionImpl::EnableAutoloadingOnStartup(BOOL bEnable/* = TRUE*/)
{
	return sv_bAutoloadingOnStartup = bEnable;
}

BOOL CMGOptionImpl::IsAutoLoadingOnStartup() const
{
	return sv_bAutoloadingOnStartup;
}


BOOL CMGOptionImpl::EnableMG(BOOL bEnable/* = TRUE*/)
{
	return sv_bMGEnabled = bEnable;
}

BOOL CMGOptionImpl::IsMGEnabled() const
{
	return sv_bMGEnabled;
}


UINT CMGOptionImpl::SetPageTopBottomRecognitionArea(UINT nPageTopBottomRecognitionArea/* = 5*/)
{
	return sv_nPageTopBottomRecognitionArea = tutil::SetInRange<UINT>(nPageTopBottomRecognitionArea, 0, MG::PageTopBottomRecognitionAreaMax);
}

UINT CMGOptionImpl::GetPageTopBottomRecognitionArea() const
{
	return sv_nPageTopBottomRecognitionArea;
}


BOOL CMGOptionImpl::EnablePageTopBottom(BOOL bEnable)
{
	return sv_bPageTopBottom = bEnable;
}

BOOL CMGOptionImpl::IsPageTopBottom() const
{
	return sv_bPageTopBottom;
}


BOOL CMGOptionImpl::EnablePageUpDown(BOOL bEnable)
{
	return sv_bPageUpDown = bEnable;
}

BOOL CMGOptionImpl::IsPageUpDown() const
{
	return sv_bPageUpDown;
}


BOOL CMGOptionImpl::EnableDblClkScrolling(BOOL bEnable)
{
	return sv_bDblClkScrollingEnabled = bEnable;
}

BOOL CMGOptionImpl::IsDblClkScrollingEnabled() const
{
	return sv_bDblClkScrollingEnabled;
}

BOOL CMGOptionImpl::UseMiddleButtonForDblClkScrolling(BOOL bUse)
{
	return sv_bUseMiddleButtonForDblClkScrolling = bUse;
}

BOOL CMGOptionImpl::IsMiddleButtonForDblClkScrolling() const
{
	return sv_bUseMiddleButtonForDblClkScrolling;	
}

/// the minimum amount of pixels over which it is required to move to be recognize as a gesture (default = 15 pixels)
UINT CMGOptionImpl::GetGestureRecognitionSensitivity() const
{
	return sv_nGestureRecognitionSensitivity;
}

UINT CMGOptionImpl::SetGestureRecognitionSensitivity(UINT nSensitivity/* = 15*/)
{
	return sv_nGestureRecognitionSensitivity = tutil::SetInRange<UINT>(nSensitivity, MG::GestureRecognitionSensitivityMin, MG::GestureRecognitionSensitivityMax);
}

/// if set, the main application will not have chance to handle, nor even to see the Mouse Gesture Activation Button down message (WM_BUTTONDOWN)
BOOL CMGOptionImpl::EnablePreemptiveMGAButtonAlways(BOOL bEnable/* = TRUE*/)
{
	return sv_bPreemptiveMGAButtonAlways = bEnable;
}

BOOL CMGOptionImpl::IsPreemptiveMGAButtonAlways() const
{
	return sv_bPreemptiveMGAButtonAlways;
}


enum MG::Button CMGOptionImpl::GetMGAButton() const
{
	return	sv_MGAButton;
}

UINT CMGOptionImpl::SetMGAButton(UINT nButton)
{
	ASSERT(nButton >= 0 && nButton <= 2); return SetMGAButton(enum MG::Button(nButton));
}

UINT CMGOptionImpl::SetMGAButton(enum MG::Button button)
{
	return sv_MGAButton = (button < MG::BUTTON_MIDDLE) ? MG::BUTTON_RIGHT : button;
}


/// VK_SHIFT, VK_CONTROL or VK_MENU
int CMGOptionImpl::SetMGSuspendingKey(int nVirtualKey)
{
	return SetMGSuspendingKey(enum MG::VirtualKey(nVirtualKey));
}

int CMGOptionImpl::SetMGSuspendingKey(enum MG::VirtualKey VirtualKey)
{
	return sv_nMGSuspendingKey = (VirtualKey == MG::VIRTUAL_SHIFT || VirtualKey == MG::VIRTUAL_ALT) ? VirtualKey : MG::VIRTUAL_CONTROL;
}

int CMGOptionImpl::GetMGSuspendingKey() const
{
	return sv_nMGSuspendingKey;
}


BOOL CMGOptionImpl::EnableMGSuspendingKey(BOOL bEnable/* = TRUE*/)
{
	return sv_bMGSuspendingKeyEnabled = bEnable;
}

BOOL CMGOptionImpl::IsMGSuspendingKeyEnabled() const
{
	return sv_bMGSuspendingKeyEnabled;
}


/// same direction repeat detection rate in msec (default = 300 ms)
UINT CMGOptionImpl::GetDetectingRepeatedSameDirectionRate() const
{
	return sv_nDetectingRepeatedSameDirectionRate;
}

UINT CMGOptionImpl::SetDetectingRepeatedSameDirectionRate(UINT nRate/* = 300*/)
{
	return sv_nDetectingRepeatedSameDirectionRate = tutil::SetInRange<UINT>(nRate, MG::DetectingRepeatedSameDirectionRateMin, MG::DetectingRepeatedSameDirectionRateMax);
}


/// show the entered mouse gesture on status bar
BOOL CMGOptionImpl::EnableShowRecognitionOnStatusBar(BOOL bEnable/* = TRUE*/)
{
	return sv_bShowRecognitionOnStatusBar = bEnable;
}

BOOL CMGOptionImpl::IsShowRecognitionOnStatusBar() const
{
	return sv_bShowRecognitionOnStatusBar;
}


/// show the target window's class name on status bar
BOOL CMGOptionImpl::EnableIdentifyTargetWindowClass(BOOL bEnable/* = TRUE*/)
{
	return sv_bIdentifyTargetWindowClass = bEnable;
}

BOOL CMGOptionImpl::IsIdentifyTargetWindowClass() const
{
	return sv_bIdentifyTargetWindowClass;
}

/// enable help tips (default popup delay time = 2000 ms)
BOOL CMGOptionImpl::EnableHelpTip(BOOL bEnable/* = TRUE*/)
{
	return sv_bHelpTipEnabled = bEnable;
}

BOOL CMGOptionImpl::IsHelpTipEnabled() const
{
	return sv_bHelpTipEnabled;
}

UINT CMGOptionImpl::SetDelayTimeHelpTip(UINT nMilliseconds/* = 2000*/)
{
	return sv_nDelayTimeHelpTip  = tutil::SetInRange<UINT>(nMilliseconds, MG::DelayTimeHelpTipMin, MG::DelayTimeHelpTipMax);
}

UINT CMGOptionImpl::GetDelayTimeHelpTip() const
{
	return sv_nDelayTimeHelpTip;
}
